package just.stuff.morsels.ui.morsel;

import java.util.Date;
import java.util.List;
import java.util.Locale;

import just.stuff.morsels.MorselApplication;
import just.stuff.morsels.objects.Morsel;
import just.stuff.morsels.ui.assist.GetAssistanceLink;
import just.stuff.morsels.ui.label.LabelList;
import just.stuff.morsels.util.DateIntervalFormat;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.convert.IConverter;

import com.petebevin.markdown.MarkdownProcessor;
import com.visural.common.web.HtmlSanitizer;

public class DisplayMorselPanel extends Panel {

	private IModel<Boolean> editFlag;
	private Component relevance;

	public DisplayMorselPanel(String id, final Morsel morsel,
			IModel<Boolean> editFlag) {
		super(id, new CompoundPropertyModel<Morsel>(morsel));
		this.editFlag = editFlag;

		addRelatedList(morsel);
		
		add(new Label("title"));
		add(new Label("text", new AbstractReadOnlyModel<String>() {
			@Override
			public String getObject() {
				String text = morsel.getText();
				if( text == null )
					return null;
				MarkdownProcessor proc = new MarkdownProcessor();
				text = proc.markdown( text );
				text = text.replaceAll( "<pre>", "<pre class=\"prettyprint\">" );
				return HtmlSanitizer.sanitizer(text).html;
			}
		}).setEscapeModelStrings(false));
		add(relevance = new Label("relevance").setOutputMarkupId(true));
		add(new Label("lastSaved") {
			
			@Override
			public IConverter getConverter(Class<?> type) {
				return new IConverter() {

					public String convertToString(Object value, Locale locale) {
						return DateIntervalFormat.format((Date)value);
					}

					public Object convertToObject(String value, Locale locale) {
						throw new UnsupportedOperationException();
					}   
				};
			}

		});
		add(new LabelList("labels", Model.of(morsel)));

		add(new VoteLink("voteUp", Model.of(morsel)) {
			@Override
			protected int alterRelevance(int current) {
				return current + 1;
			}
		});
		add(new VoteLink("voteDown", Model.of(morsel)) {
			@Override
			protected int alterRelevance(int current) {
				return current - 1;
			}
		});
		
		addEditLink(editFlag);
		
		add( new GetAssistanceLink( "assistance", morsel ) );

	}

	private void addEditLink(IModel<Boolean> editFlag) {
		AjaxLink<Boolean> editLink = new AjaxLink<Boolean>("editLink", editFlag) {
			@Override
			public void onClick(AjaxRequestTarget target) {
				setModelObject(true);
			}

			@Override
			public boolean isVisible() {
				return !getModelObject();
			}
		};
		editLink.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
		add(editLink);
	}

	private void addRelatedList(final Morsel morsel) {
		List<Morsel> relatedList = null;
		try {
			relatedList = MorselApplication.dataSource().findRelated( morsel );
		} catch (Exception e) {
			//TODO: error logging
			e.printStackTrace();
		}
		
		final IModel<List<? extends Morsel>> model = Model.ofList( relatedList );
		WebMarkupContainer related = new WebMarkupContainer( "related" ) {
			@Override
			public boolean isVisible() {
				return model.getObject() != null && !model.getObject() .isEmpty();
			}
		};
		related.add( new MorselList( "list", model ));
		add( related );
	}

	@Override
	public boolean isVisible() {
		return !editFlag.getObject();
	}

	/**
	 * Abstract class for voting links 
	 */
	private abstract class VoteLink extends AjaxLink<Morsel> {
		public VoteLink(String id, IModel<Morsel> model) {
			super(id, model);
		}

		@Override
		public void onClick(AjaxRequestTarget target) {
			Morsel morsel = getModelObject();
			int rel = morsel.getRelevance();
			rel = alterRelevance(rel);
			morsel.setRelevance(rel);
			MorselApplication.dataSource().save(morsel);
			target.addComponent(relevance);
		}

		protected abstract int alterRelevance(int current);

	}

}

